/*
 *
 * Copyright Eclub organization.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.eclub.emotion.rootstone.serializer.scanning;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URI;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Stack;

import com.eclub.emotion.rootstone.server.ResourceFinder;

/**
 * A "file" scheme URI scanner that recursively scans directories.
 *
 * @author   jun.yang, Wincor Nixdorf International GmbH
 * @version  $Revision$
 */
class FileSchemeResourceFinderFactory implements UriSchemeResourceFinderFactory {

	@Override
    public Set<String> getSchemes() {
        return Collections.singleton("file");
    }

    FileSchemeResourceFinderFactory() {
    }

    @Override
    public FileSchemeScanner create(URI uri) {
        return new FileSchemeScanner(uri);
    }

    private class FileSchemeScanner implements ResourceFinder {

        private ResourceFinderStack resourceFinderStack = null;

        private FileSchemeScanner(final URI uri) {
            resourceFinderStack = new ResourceFinderStack();
            processFile(new File(uri.getPath()));
        }

        @Override
        public boolean hasNext() {
            return resourceFinderStack.hasNext();
        }

        @Override
        public String next() {
            return resourceFinderStack.next();
        }

        @Override
        public void remove() {
            resourceFinderStack.remove();
        }

        @Override
        public InputStream open() {
            return resourceFinderStack.open();
        }

        @Override
        public void reset() {
            throw new UnsupportedOperationException();
        }

        private void processFile(final File f) {
            resourceFinderStack.push(new ResourceFinder() {

                Stack<File> files = new Stack<File>() {{
                    if(f.isDirectory()) {
                        for(File file : f.listFiles()) {
                            push(file);
                        }
                    } else {
                        push(f);
                    }
                }};

                private File current;
                private File next;

                @Override
                public boolean hasNext() {
                    while(next == null && !files.empty()) {
                        next = files.pop();

                        if(next.isDirectory()) {
                            processFile(next);
                            next = null;
                        }
                    }

                    return next != null;
                }

                @Override
                public String next() {
                    if(next != null || hasNext()) {
                        current = next;
                        next = null;
                        return current.getName();
                    }

                    throw new NoSuchElementException();
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }

                @Override
                public InputStream open() {
                    try {
                        return new FileInputStream(current);
                    } catch (FileNotFoundException e) {
                        throw new ResourceFinderException(e);
                    }
                }

                @Override
                public void reset() {
                    throw new UnsupportedOperationException();
                }
            });
        }
    }

}


